# experiment.py
#
# Place to experiment with PyRadiosity

from xmlscenereader import readScene
from xmlscenewriter import writeScene
from xmlscene_functions import *
from triangulatedpolygon import TriangulatedPolygon
from patch import *
from formfactor import *
from transformations import *
from gl_functions import *
from radiosity_relaxation import *

def initializeScene(infile, subdivision=10.0):
    scene = readScene(infile)
    patches = createPatches(scene, applyMacros(scene), subdivision)
    arrays = createGlArraysForPatches(patches) # from experimentCachingFormFactors, arrays are slightly faster
    formfactorengine = HemicubeFormFactorEngine(patches=patches, resolution=256, arrays=arrays)

    return scene, patches, formfactorengine

def experimentTestScene(relaxation_function, outfile_prefix, patches, formfactorengine, cached_form_factors, notifier, convergence_threshold="0.00001,0.00001,0.00001"):
    guess = relaxation_function(patches=patches,
                                formfactorengine=formfactorengine,
                                convergence_threshold=convergence_threshold,
                                cached_form_factors=cached_form_factors,
                                notifier=notifier)
    guess_updates = notifier.guess_updates[relaxation_function]
    for guess_update in guess_updates:
        outfile = outfile_prefix + relaxation_function.__name__ + "_iteration_" + str(guess_update[1]) + ".xml"
        updatePatchesInGuess(guess_update[0])
        computed_scene = convertPatchesToXmlScene(patches)
        writeScene(computed_scene, outfile)

def experimentMemoizingFormFactors(patches, formfactor_engine, outfile, resolution=256, infile=""):
    print "Experimenting on memoizing form factors in engine " + formfactor_engine.toString() + "..."

    len_patches = len(patches)
    experiment_variables = [] # will track patch index, # of patches in form factors, time it took to calculate, length of cache to that point

    formfactor_engine.memoizeFormFactors(len_patches)

    total_ffs = 0
    for i in xrange(len_patches):
        start = time.time()
        formfactor_engine.computeFormFactorsForPatch(patches[i])
        end = time.time()

        memoized_ffs = formfactor_engine.memoizedFormFactors()
        total_ffs += len(memoized_ffs[patches[i]])
        variable = [i, len(memoized_ffs[patches[i]]), end-start, total_ffs]
        experiment_variables.append(variable)

    file = open(outfile, 'w')
    file.write('Experiment on memoizing form factors in engine ' + formfactor_engine.toString() + '\n\n')
    file.write('Parameters:\n')
    file.write('    Scene description file = ' + infile + '\n')
    file.write('    # of patches cached = ' + str(len(patches)) + '\n')
    file.write('\n')
    file.write('Results:\n')
    file.write('    Patch    # of form factors    Form Factor Compute Time (sec)    Length of cache\n')
    for var in experiment_variables:
        file.write('    ')
        for e in var:
            file.write(str(e) + ',  ')
        file.write('\n')
    
    print "  Done; results written to ", outfile

if __name__ == '__main__':
    import time
    import sys
    import getopt
    OpenGL.ERROR_CHECKING = False

    do_relaxation_comparisons = False
    subdivisions = 100.0
    do_cache_timing = False
    use_display_list = True
    use_gl_arrays = False
    use_vbos = False
    use_hemicube_ffe = True
    test_scene = "./xml_test_files/test_scene_patch.xml"
    res = 256
    try:
        opts, args = getopt.getopt(sys.argv[1:], "r:mf:s:g:", ["relaxation=", "memoize", "formfactorengine=", "scene=", "gl-drawing="])
        for opt, arg in opts:
            if opt in ["-r", "--relaxation"]:
                do_relaxation_comparisons = True
                subdivisions = float(arg)
            elif opt in ["-m", "--memoize"]:
                do_cache_timing = True
            elif opt in ["-f", "--formfactorengine"]:
                if arg == "hemicube":
                    use_hemicube_ffe = True
            elif opt in ["-s", "--scene"]:
                test_scene = arg
            elif opt in ["-g", "--gl-drawing"]:
                if arg == "display-list":
                    use_display_list = True
                    use_gl_arrays = False
                elif arg == "arrays":
                    use_gl_arrays = True
                    use_display_list = False
    except:
        sys.exit(2)

    if do_cache_timing is True:
        for i in [1000000, 100, 40, 10, 5, 3, 1]:
            ffe = None
            display_list = None
            vbos = None
            arrays = None

            scene = readScene(test_scene)
            patches = createPatches(scene, applyMacros(scene), float(i))

            outfile = "./experiments/memoize_experiment_"

            if use_hemicube_ffe is True:
                ffe = HemicubeFormFactorEngine(patches=patches, resolution=res, display_list=display_list, arrays=arrays, createGLUTRenderingContext=True)
            outfile += ffe.toString() + "_"
            
            if use_display_list:
                outfile += "display_list_"
                display_list = createGL_TRIANGLESDisplayListForPatches(patches)
            elif use_gl_arrays:
                outfile += "gl_arrays_"
                arrays = createGlArraysForPatches(patches)
            elif use_vbos:
                outfile += "vbos_"
                vbos = createVBOsForPatches(patches)
            
            outfile += str(i)
            outfile += ".txt"
                                               
            experimentMemoizingFormFactors(patches, ffe, outfile, res, test_scene)

    if do_relaxation_comparisons is True:
        print "Relaxation Comparisons"
        scene, patches, formfactorengine = initializeScene("./xml_test_files/test_scene_patch.xml", subdivisions)
        print "  Caching form factors..."
        cached_form_factors = cacheFormFactors(patches, formfactorengine, len(patches))
        print "      done"
        print ""

        print "  Computing radiosities..."
        notifier = RadiosityRelaxationNotifier()
        prefix = "./experiments/test_scene_patch_"
        experimentTestScene(radiosityRelaxation_JacobiIteration, prefix,
                            patches, formfactorengine, cached_form_factors, notifier)
        experimentTestScene(radiosityRelaxation_GaussSeidelIteration, prefix,
                            patches, formfactorengine, cached_form_factors, notifier)
        experimentTestScene(radiosityRelaxation_SouthwellIteration, prefix,
                            patches, formfactorengine, cached_form_factors, notifier)
        experimentTestScene(radiosityRelaxation_ProgressiveRefinement, prefix,
                            patches, formfactorengine, cached_form_factors, notifier)
        print "        done"
